(/) describe & visualize single variables (univariate) (/) gather interesting observations for further investigation (/) gather possible new features for extraction
todos: (-) …
name: makeovermonday_2021w22 link: https://data.world/makeovermonday/2021w22 title: 2021/W22: The Plastic Waste Makers Index Data Source: Minderoo from 2019
- no_of_assets is poisson distributed, where most producer only have up to 9 (median = 6) assets, some have up to 29 (upper fence = 26), and only a few (outliers) are above that with up to 82 assets
- production_of_in_scope_polymers is poisson distributed, likes very similar to no_of_assets, median is 0.9, upper fence is 3.4, max is 11.6 -> might correlate with no_of_assets?
- flexible_format_contribution_to_sup_waste is poisson distributed, likes very similar to no_of_assets, median is 0.2, upper fence is 1.1, max is 4.7
- rigid_format_contribution_to_sup_waste is poisson distributed, likes very similar to no_of_assets, median is 0.2, upper fence is 1.1, max is 4.5, very similar to flexible_format_contribution_to_sup_waste, but with less outliers
- rigid_format_contribution_to_sup_waste is poisson distributed, likes very similar to no_of_assets (again), median is 0.45, upper fence is 1.9, max is 5.9 is sum of flexible_form + rigid_form
- ration of sup_waste to produced polymers is between min 0.3 and max 1.0 and has median 0.5, most data lies between 0.4 and 0.6, but there is a high spike at 1.0 (with count 15)
- comparing rigid_format and flexible_format shows that up to the upper fence 1.1, the distribution is similar, but there are more bigger (>3) outliers in flexible
head(plastic)
summary(plastic)
rank polymer_producer no_of_assets production_of_in_scope_polymers flexible_format_contribution_to_sup_waste rigid_format_contribution_to_sup_waste
Min. : 1.00 Length:100 Min. : 0.00 Min. : 0.200 Min. :0.000 Min. :0.000
1st Qu.: 25.75 Class :character 1st Qu.: 3.00 1st Qu.: 0.500 1st Qu.:0.100 1st Qu.:0.100
Median : 50.50 Mode :character Median : 6.00 Median : 0.900 Median :0.200 Median :0.200
Mean : 50.50 Mean :11.56 Mean : 1.805 Mean :0.538 Mean :0.416
3rd Qu.: 75.25 3rd Qu.:12.25 3rd Qu.: 1.700 3rd Qu.:0.500 3rd Qu.:0.500
Max. :100.00 Max. :82.00 Max. :11.600 Max. :4.700 Max. :4.500
total_contribution_to_sup_waste total_waste_div_production
Min. :0.200 Min. :0.3000
1st Qu.:0.300 1st Qu.:0.4300
Median :0.450 Median :0.5000
Mean :0.950 Mean :0.5834
3rd Qu.:0.925 3rd Qu.:0.6900
Max. :5.900 Max. :1.0000
no_of_assets is poisson distributed, where most producer only have up to 9 (median = 6) assets, some have up to 29 (upper fence = 26), and only a few (outliers) are above that with up to 82 assets
name = 'no_of_assets'
df <- plastic %>% rename(value = no_of_assets) %>% select(value)
# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
ggplot(aes(x = value)) +
# geom_density() +
geom_histogram(binwidth = 1) +
# geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1.1, dotsize = 1.2, binwidth = 1) +
theme_minimal() +
scale_y_continuous(breaks = NULL)
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
boxplot <- df %>%
ggplot(aes(x = 1, y = value)) +
geom_boxplot() +
theme_minimal() +
coord_flip() +
ggtitle(paste("distribution of", name, sep=" ")) +
scale_y_continuous(breaks = NULL)
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://ggplot2.tidyverse.org/reference/geom_qq.html
plot_qq <- df %>%
ggplot(aes(sample = value)) +
geom_qq(alpha = 0.5) +
geom_qq_line() +
coord_flip() +
theme_minimal()
plot_qq <- ggplotly(plot_qq) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(title = name))
# https://plotly.com/r/subplots/
fig <- subplot(dotplot, boxplot, plot_qq, nrows = 3, margin = 0, heights = c(0.5, 0.2, 0.3), shareX = TRUE)
fig
| univariate production_of_in_scope_polymers |
production_of_in_scope_polymers is poisson distributed, likes very similar to no_of_assets, median is 0.9, upper fence is 3.4, max is 11.6 might correlate with no_of_assets?
name = 'production_of_in_scope_polymers'
df <- plastic %>% rename(value = production_of_in_scope_polymers) %>% select(value)
# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
ggplot(aes(x = value)) +
# geom_density() +
geom_histogram(binwidth = 0.1) +
# geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1.1, dotsize = 1.2, binwidth = 1) +
theme_minimal() +
scale_y_continuous(breaks = NULL)
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
boxplot <- df %>%
ggplot(aes(x = 1, y = value)) +
geom_boxplot() +
theme_minimal() +
coord_flip() +
ggtitle(paste("distribution of", name, sep=" ")) +
scale_y_continuous(breaks = NULL)
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://ggplot2.tidyverse.org/reference/geom_qq.html
plot_qq <- df %>%
ggplot(aes(sample = value)) +
geom_qq(alpha = 0.5) +
geom_qq_line() +
coord_flip() +
theme_minimal()
plot_qq <- ggplotly(plot_qq) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(title = name))
# https://plotly.com/r/subplots/
fig <- subplot(dotplot, boxplot, plot_qq, nrows = 3, margin = 0, heights = c(0.5, 0.2, 0.3), shareX = TRUE)
fig
| univariate flexible_format_contribution_to_sup_waste |
flexible_format_contribution_to_sup_waste is poisson distributed, likes very similar to no_of_assets, median is 0.2, upper fence is 1.1, max is 4.7
# one variable. continuous x
name = 'flexible_format_contribution_to_sup_waste'
df <- plastic %>% rename(value = flexible_format_contribution_to_sup_waste) %>% select(value)
# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
ggplot(aes(x = value)) +
# geom_density() +
geom_histogram(binwidth = 0.1) +
# geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1.1, dotsize = 1.2, binwidth = 1) +
theme_minimal() +
scale_y_continuous(breaks = NULL)
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
boxplot <- df %>%
ggplot(aes(x = 1, y = value)) +
geom_boxplot() +
theme_minimal() +
coord_flip() +
ggtitle(paste("distribution of", name, sep=" ")) +
scale_y_continuous(breaks = NULL)
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://ggplot2.tidyverse.org/reference/geom_qq.html
plot_qq <- df %>%
ggplot(aes(sample = value)) +
geom_qq(alpha = 0.5) +
geom_qq_line() +
coord_flip() +
theme_minimal()
plot_qq <- ggplotly(plot_qq) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(title = name))
# https://plotly.com/r/subplots/
fig <- subplot(dotplot, boxplot, plot_qq, nrows = 3, margin = 0, heights = c(0.5, 0.2, 0.3), shareX = TRUE)
fig
| univariate rigid_format_contribution_to_sup_waste |
rigid_format_contribution_to_sup_waste is poisson distributed, likes very similar to no_of_assets, median is 0.2, upper fence is 1.1, max is 4.5, very similar to flexible_format_contribution_to_sup_waste, but with less outliers
name = 'rigid_format_contribution_to_sup_waste'
df <- plastic %>% rename(value = rigid_format_contribution_to_sup_waste) %>% select(value)
# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
ggplot(aes(x = value)) +
# geom_density() +
geom_histogram(binwidth = 0.1) +
# geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1.1, dotsize = 1.2, binwidth = 1) +
theme_minimal() +
scale_y_continuous(breaks = NULL)
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
boxplot <- df %>%
ggplot(aes(x = 1, y = value)) +
geom_boxplot() +
theme_minimal() +
coord_flip() +
ggtitle(paste("distribution of", name, sep=" ")) +
scale_y_continuous(breaks = NULL)
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://ggplot2.tidyverse.org/reference/geom_qq.html
plot_qq <- df %>%
ggplot(aes(sample = value)) +
geom_qq(alpha = 0.5) +
geom_qq_line() +
coord_flip() +
theme_minimal()
plot_qq <- ggplotly(plot_qq) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(title = name))
# https://plotly.com/r/subplots/
fig <- subplot(dotplot, boxplot, plot_qq, nrows = 3, margin = 0, heights = c(0.5, 0.2, 0.3), shareX = TRUE)
fig
| univariate total_contribution_to_sup_waste |
rigid_format_contribution_to_sup_waste is poisson distributed, likes very similar to no_of_assets (again), median is 0.45, upper fence is 1.9, max is 5.9 is sum of flexible_form + rigid_form
name = 'total_contribution_to_sup_waste'
df <- plastic %>% rename(value = total_contribution_to_sup_waste) %>% select(value)
# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
ggplot(aes(x = value)) +
# geom_density() +
geom_histogram(binwidth = 0.1) +
# geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1.1, dotsize = 1.2, binwidth = 1) +
theme_minimal() +
scale_y_continuous(breaks = NULL)
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
boxplot <- df %>%
ggplot(aes(x = 1, y = value)) +
geom_boxplot() +
theme_minimal() +
coord_flip() +
ggtitle(paste("distribution of", name, sep=" ")) +
scale_y_continuous(breaks = NULL)
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://ggplot2.tidyverse.org/reference/geom_qq.html
plot_qq <- df %>%
ggplot(aes(sample = value)) +
geom_qq(alpha = 0.5) +
geom_qq_line() +
coord_flip() +
theme_minimal()
plot_qq <- ggplotly(plot_qq) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(title = name))
# https://plotly.com/r/subplots/
fig <- subplot(dotplot, boxplot, plot_qq, nrows = 3, margin = 0, heights = c(0.5, 0.2, 0.3), shareX = TRUE)
fig
| univariate total_waste_div_production |
ration of sup_waste to produced polymers is between min 0.3 and max 1.0 and has median 0.5, most data lies between 0.4 and 0.6, but there is a high spike at 1.0 (with count 15)
name = 'total_waste_div_production'
df <- plastic %>% rename(value = total_waste_div_production) %>% select(value)
# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
ggplot(aes(x = value)) +
# geom_density() +
geom_histogram(binwidth = 0.01) +
# geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1.1, dotsize = 1.2, binwidth = 1) +
theme_minimal() +
scale_y_continuous(breaks = NULL)
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
boxplot <- df %>%
ggplot(aes(x = 1, y = value)) +
geom_boxplot() +
theme_minimal() +
coord_flip() +
ggtitle(paste("distribution of", name, sep=" ")) +
scale_y_continuous(breaks = NULL)
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://ggplot2.tidyverse.org/reference/geom_qq.html
plot_qq <- df %>%
ggplot(aes(sample = value)) +
geom_qq(alpha = 0.5) +
geom_qq_line() +
coord_flip() +
theme_minimal()
plot_qq <- ggplotly(plot_qq) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE), xaxis = list(title = name))
# https://plotly.com/r/subplots/
fig <- subplot(dotplot, boxplot, plot_qq, nrows = 3, margin = 0, heights = c(0.5, 0.2, 0.3), shareX = TRUE)
fig
| compare rigid_format and flexible_format |
comparing rigid_format and flexible_format shows that up to the upper fence 1.1, the distribution is similar, but there are more bigger (>3) outliers in flexible
# two variables, both continuous x, compare distributions
name = c('flexible_format_contribution_to_sup_waste', 'rigid_format_contribution_to_sup_waste')
df <- plastic %>% rename(flexible = flexible_format_contribution_to_sup_waste, rigid = rigid_format_contribution_to_sup_waste) %>% select(flexible, rigid) %>% pivot_longer(cols = c(flexible,rigid))
boxplot <- df %>%
ggplot(aes(x = name, y = value, colour = name)) +
geom_boxplot() +
theme_minimal() +
coord_flip() +
ggtitle(paste("compare ", name[1], "and", name[2], sep=" ")) +
scale_y_continuous(breaks = NULL)
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
ggplot(aes(x = value, fill = name)) +
# geom_density() +
geom_histogram(binwidth = 0.1, alpha = 0.5, position = "identity") +
# geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1, dotsize = 0.23, binwidth = 0.1) +
theme_minimal() +
scale_y_continuous(breaks = NULL)
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://ggplot2.tidyverse.org/reference/geom_qq.html
plot_qq <- df %>%
ggplot(aes(sample = value, colour = name)) +
geom_qq(alpha = 0.5) +
geom_qq_line(alpha = 0.5) +
coord_flip() +
theme_minimal()
plot_qq <- ggplotly(plot_qq) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://plotly.com/r/subplots/
fig <- subplot(dotplot, boxplot, plot_qq, nrows = 3, margin = 0, heights = c(0.5, 0.2, 0.3), shareX = TRUE) %>% layout(xaxis = list(title = paste(name[1], "<br>", name[2], sep="")))
fig
assets_plot_hist <- plastic %>%
ggplot(aes(x = no_of_assets)) +
geom_histogram(binwidth = 1) +
theme_minimal() +
ggtitle("Distribution of no_of_assets")
ggplotly(assets_plot_hist)
assets_plot_box <- plastic %>%
ggplot(aes(x = 1, y = no_of_assets)) +
geom_boxplot() +
geom_jitter(alpha = 0.5, width = 0.15) +
theme_minimal() +
coord_flip() +
ggtitle("Distribution of no_of_assets")
ggplotly(assets_plot_box)
assets_plot_box <- plastic %>%
mutate( x = 1 ) %>%
ggplot(aes(y = no_of_assets, x=1)) +
geom_boxplot() +
geom_dotplot(binaxis='y', stackdir='center', binwidth = 1) +
theme_minimal() +
coord_flip() +
ggtitle("Distribution of no_of_assets")
assets_plot_box

assets_plot_density <- plastic %>%
ggplot(aes(x = no_of_assets)) +
geom_histogram(aes(y=..density..)) +
geom_density() +
theme_minimal() +
ggtitle("Distribution of no_of_assets")
ggplotly(assets_plot_density)
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
assets_plot_dot <- plastic %>%
ggplot(aes(x = no_of_assets)) +
geom_histogram(binwidth = 1) +
geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1.1, dotsize = 1, binwidth = 1) +
theme_minimal() +
scale_y_continuous(breaks = NULL) +
ggtitle("Distribution of no_of_assets")
assets_plot_dot

name = 'no_of_assets'
df <- plastic %>% rename(y = no_of_assets) %>% select(y)
# https://ggplot2.tidyverse.org/reference/geom_qq.html
plot_qq <- df %>%
ggplot(aes(sample = y)) +
geom_qq() +
geom_qq_line() +
theme_minimal() +
ggtitle(paste("qq plot for", name, sep=" "))
plot_qq <- ggplotly(plot_qq)
# Use fitdistr from MASS to estimate distribution params
# https://rdrr.io/cran/MASS/man/fitdistr.html
params <- as.list(MASS::fitdistr(df$y, "t")$estimate)
NaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugt
plot_qq_fit <- df %>%
ggplot(aes(sample = y)) +
geom_qq(distribution = qt, dparams = params["df"]) +
geom_qq_line(distribution = qt, dparams = params["df"]) +
theme_minimal() +
ggtitle(paste("qq plot for", name, "without left and with fitdistr right", sep=" "))
plot_qq_fit <- ggplotly(plot_qq_fit)
# https://plotly.com/r/subplots/
subplot(plot_qq, plot_qq_fit)
name = 'production_of_in_scope_polymers'
df <- plastic %>% rename(y = production_of_in_scope_polymers) %>% select(y)
boxplot <- df %>%
ggplot(aes(x = 1, y = y)) +
geom_boxplot() +
theme_minimal() +
coord_flip() +
ggtitle(paste("distribution of", name, sep=" ")) +
scale_y_continuous(breaks = NULL)
boxplot <- ggplotly(boxplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://ggplot2.tidyverse.org/reference/geom_dotplot.html
dotplot <- df %>%
ggplot(aes(x = y)) +
# geom_density() +
# geom_histogram(binwidth = 1) +
geom_dotplot(method="histodot", stackgroups = TRUE, stackratio = 1.1, dotsize = 1.2, binwidth = 0.1) +
theme_minimal() +
scale_y_continuous(breaks = NULL)
dotplot <- ggplotly(dotplot) %>% layout(yaxis = list(showticklabels = FALSE, showgrid = FALSE))
# https://ggplot2.tidyverse.org/reference/geom_qq.html
plot_qq <- df %>%
ggplot(aes(sample = y)) +
geom_qq() +
geom_qq_line() +
theme_minimal()
# Use fitdistr from MASS to estimate distribution params
params <- as.list(MASS::fitdistr(df$y, "t")$estimate)
NaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugtNaNs wurden erzeugt
plot_qq_fit <- df %>%
ggplot(aes(sample = y)) +
geom_qq(distribution = qt, dparams = params["df"]) +
geom_qq_line(distribution = qt, dparams = params["df"]) +
theme_minimal()
# https://plotly.com/r/subplots/
s1 <- subplot(dotplot, boxplot, nrows = 2, margin = 0.03, heights = c(0.75, 0.25))
s2 <- subplot(plot_qq, plot_qq_fit)
fig <- subplot(s1, s2, nrows = 2, margin = 0.03, heights = c(0.6, 0.4))
fig
LS0tDQp0aXRsZTogImRlc2NyaWJlIGFuZCB2aXN1YWxpemUgcGxhc3RpYyB3YXN0ZSBtYWtlcnMgaW5kZXggZGF0YSAtIHVuaXZhcmlhdGUiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQotLS0NCnB1cnBvc2Ugb2Ygbm90ZWJvb2sNCi0tLQ0KDQogICgvKSBkZXNjcmliZSAmIHZpc3VhbGl6ZSBzaW5nbGUgdmFyaWFibGVzICh1bml2YXJpYXRlKQ0KICAoLykgZ2F0aGVyIGludGVyZXN0aW5nIG9ic2VydmF0aW9ucyBmb3IgZnVydGhlciBpbnZlc3RpZ2F0aW9uDQogICgvKSBnYXRoZXIgcG9zc2libGUgbmV3IGZlYXR1cmVzIGZvciBleHRyYWN0aW9uDQogIA0KdG9kb3M6DQogICgtKSAuLi4NCiAgDQotLS0NCmluZm9ybWF0aW9uDQotLS0NCg0KbmFtZTogbWFrZW92ZXJtb25kYXlfMjAyMXcyMg0KbGluazogaHR0cHM6Ly9kYXRhLndvcmxkL21ha2VvdmVybW9uZGF5LzIwMjF3MjINCnRpdGxlOiAyMDIxL1cyMjogVGhlIFBsYXN0aWMgV2FzdGUgTWFrZXJzIEluZGV4DQpEYXRhIFNvdXJjZTogW01pbmRlcm9vXShodHRwczovL3d3dy5taW5kZXJvby5vcmcvcGxhc3RpYy13YXN0ZS1tYWtlcnMtaW5kZXgvZGF0YS9pbmRpY2VzL3Byb2R1Y2Vycy8pIGZyb20gMjAxOQ0KICANCi0tLQ0KaW5zaWdodHMgDQotLS0NCg0KICAoaSkgbm9fb2ZfYXNzZXRzIGlzIHBvaXNzb24gZGlzdHJpYnV0ZWQsIHdoZXJlIG1vc3QgcHJvZHVjZXIgb25seSBoYXZlIHVwIHRvIDkgKG1lZGlhbiA9IDYpIGFzc2V0cywgc29tZSBoYXZlIHVwIHRvIDI5ICh1cHBlciBmZW5jZSA9IDI2KSwgYW5kIG9ubHkgYSBmZXcgKG91dGxpZXJzKSBhcmUgYWJvdmUgdGhhdCAgICAgICAgd2l0aCB1cCB0byA4MiBhc3NldHMNCiAgKGkpIHByb2R1Y3Rpb25fb2ZfaW5fc2NvcGVfcG9seW1lcnMgaXMgcG9pc3NvbiBkaXN0cmlidXRlZCwgbGlrZXMgdmVyeSBzaW1pbGFyIHRvIG5vX29mX2Fzc2V0cywgbWVkaWFuIGlzIDAuOSwgdXBwZXIgZmVuY2UgaXMgMy40LCBtYXggaXMgMTEuNg0KICAgICAgLT4gbWlnaHQgY29ycmVsYXRlIHdpdGggbm9fb2ZfYXNzZXRzPw0KICAoaSkgZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgaXMgcG9pc3NvbiBkaXN0cmlidXRlZCwgbGlrZXMgdmVyeSBzaW1pbGFyIHRvIG5vX29mX2Fzc2V0cywgbWVkaWFuIGlzIDAuMiwgdXBwZXIgZmVuY2UgaXMgMS4xLCBtYXggaXMgNC43DQogIChpKSByaWdpZF9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSBpcyBwb2lzc29uIGRpc3RyaWJ1dGVkLCBsaWtlcyB2ZXJ5IHNpbWlsYXIgdG8gbm9fb2ZfYXNzZXRzLCBtZWRpYW4gaXMgMC4yLCB1cHBlciBmZW5jZSBpcyAxLjEsIG1heCBpcyA0LjUsDQogICAgICB2ZXJ5IHNpbWlsYXIgdG8gZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUsIGJ1dCB3aXRoIGxlc3Mgb3V0bGllcnMNCiAgKGkpIHJpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlIGlzIHBvaXNzb24gZGlzdHJpYnV0ZWQsIGxpa2VzIHZlcnkgc2ltaWxhciB0byBub19vZl9hc3NldHMgKGFnYWluKSwgbWVkaWFuIGlzIDAuNDUsIHVwcGVyIGZlbmNlIGlzIDEuOSwgbWF4IGlzIDUuOQ0KICAgICAgaXMgc3VtIG9mIGZsZXhpYmxlX2Zvcm0gKyByaWdpZF9mb3JtDQogIChpKSByYXRpb24gb2Ygc3VwX3dhc3RlIHRvIHByb2R1Y2VkIHBvbHltZXJzIGlzIGJldHdlZW4gbWluIDAuMyBhbmQgbWF4IDEuMCBhbmQgaGFzIG1lZGlhbiAwLjUsIG1vc3QgZGF0YSBsaWVzIGJldHdlZW4gMC40IGFuZCAwLjYsIGJ1dCB0aGVyZSBpcyBhIGhpZ2ggc3Bpa2UgYXQgMS4wICh3aXRoIGNvdW50IDE1KQ0KICAoaSkgY29tcGFyaW5nIHJpZ2lkX2Zvcm1hdCBhbmQgZmxleGlibGVfZm9ybWF0IHNob3dzIHRoYXQgdXAgdG8gdGhlIHVwcGVyIGZlbmNlIDEuMSwgdGhlIGRpc3RyaWJ1dGlvbiBpcyBzaW1pbGFyLCBidXQgdGhlcmUgYXJlIG1vcmUgYmlnZ2VyICg+Mykgb3V0bGllcnMgaW4gZmxleGlibGUNCiAgIA0KLS0tDQpsb2FkIHBhY2thZ2VzDQotLS0NCmBgYHtyIGxvYWQgcGFja2FnZXMsIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpICMgdGlkeSBkYXRhIGZyYW1lDQpsaWJyYXJ5KGdndGhlbWVzKSAjIGZvciBleHRyYSBwbG90IHRoZW1lcw0KbGlicmFyeShwbG90bHkpICMgbWFrZSBnZ3Bsb3RzIGludGVyYWN0aXZlDQoNCmxpYnJhcnkocGF0Y2h3b3JrKSAjIG1ha2UgaXQgcmlkaWN1bG91c2x5IHNpbXBsZSB0byBjb21iaW5lIHNlcGFyYXRlIGdncGxvdHMgaW50byB0aGUgc2FtZSBncmFwaGljIHAxICsgcDIgb3IgKHAxIHwgcDIgfCBwMykgLyBwNA0KbGlicmFyeShkbG9va3IpICMgY29sbGVjdGlvbiBvZiB0b29scyB0aGF0IHN1cHBvcnQgZGF0YSBkaWFnbm9zaXMsIGV4cGxvcmF0aW9uLCBhbmQgdHJhbnNmb3JtYXRpb24uDQpgYGANCg0KLS0tDQpvdmVydmlldw0KLS0tDQpgYGB7cn0NCmhlYWQocGxhc3RpYykNCmBgYA0KYGBge3J9DQpzdW1tYXJ5KHBsYXN0aWMpDQpgYGANCg0KLS0tDQp1bml2YXJpYXRlIG5vX29mX2Fzc2V0cw0KLS0tDQpub19vZl9hc3NldHMgaXMgcG9pc3NvbiBkaXN0cmlidXRlZCwgd2hlcmUgbW9zdCBwcm9kdWNlciBvbmx5IGhhdmUgdXAgdG8gOSAobWVkaWFuID0gNikgYXNzZXRzLCBzb21lIGhhdmUgdXAgdG8gMjkgKHVwcGVyIGZlbmNlID0gMjYpLCBhbmQgb25seSBhIGZldyAob3V0bGllcnMpIGFyZSBhYm92ZSB0aGF0IHdpdGggdXAgdG8gODIgYXNzZXRzDQoNCmBgYHtyfQ0KIyBvbmUgdmFyaWFibGUsIGNvbnRpbnVvdXMgeCwgc2hvdyBkaXN0cmlidXRpb24NCm5hbWUgPSAnbm9fb2ZfYXNzZXRzJw0KZGYgPC0gcGxhc3RpYyAlPiUgcmVuYW1lKHZhbHVlID0gbm9fb2ZfYXNzZXRzKSAlPiUgc2VsZWN0KHZhbHVlKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX2RvdHBsb3QuaHRtbA0KZG90cGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gdmFsdWUpKSArDQogICAgIyBnZW9tX2RlbnNpdHkoKSArDQogICAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgIyBnZW9tX2RvdHBsb3QobWV0aG9kPSJoaXN0b2RvdCIsIHN0YWNrZ3JvdXBzID0gVFJVRSwgc3RhY2tyYXRpbyA9IDEuMSwgZG90c2l6ZSA9IDEuMiwgYmlud2lkdGggPSAxKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkgDQpkb3RwbG90IDwtIGdncGxvdGx5KGRvdHBsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQpib3hwbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAxLCB5ID0gdmFsdWUpKSArDQogICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBnZ3RpdGxlKHBhc3RlKCJkaXN0cmlidXRpb24gb2YiLCBuYW1lLCBzZXA9IiAiKSkgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBOVUxMKSANCmJveHBsb3QgPC0gZ2dwbG90bHkoYm94cGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXEuaHRtbCANCnBsb3RfcXEgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoc2FtcGxlID0gdmFsdWUpKSArDQogICAgZ2VvbV9xcShhbHBoYSA9IDAuNSkgKw0KICAgIGdlb21fcXFfbGluZSgpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIHRoZW1lX21pbmltYWwoKQ0KcGxvdF9xcSA8LSBnZ3Bsb3RseShwbG90X3FxKSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZSkpDQoNCiMgaHR0cHM6Ly9wbG90bHkuY29tL3Ivc3VicGxvdHMvDQpmaWcgPC0gc3VicGxvdChkb3RwbG90LCBib3hwbG90LCBwbG90X3FxLCBucm93cyA9IDMsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuNSwgMC4yLCAwLjMpLCBzaGFyZVggPSBUUlVFKSANCg0KZmlnDQpgYGANCg0KLS0tDQp1bml2YXJpYXRlIHByb2R1Y3Rpb25fb2ZfaW5fc2NvcGVfcG9seW1lcnMNCi0tLQ0KcHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycyBpcyBwb2lzc29uIGRpc3RyaWJ1dGVkLCBsaWtlcyB2ZXJ5IHNpbWlsYXIgdG8gbm9fb2ZfYXNzZXRzLCBtZWRpYW4gaXMgMC45LCB1cHBlciBmZW5jZSBpcyAzLjQsIG1heCBpcyAxMS42DQptaWdodCBjb3JyZWxhdGUgd2l0aCBub19vZl9hc3NldHM/DQoNCmBgYHtyfQ0KIyBvbmUgdmFyaWFibGUsIGNvbnRpbnVvdXMgeCwgc2hvdyBkaXN0cmlidXRpb24NCm5hbWUgPSAncHJvZHVjdGlvbl9vZl9pbl9zY29wZV9wb2x5bWVycycNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh2YWx1ZSA9IHByb2R1Y3Rpb25fb2ZfaW5fc2NvcGVfcG9seW1lcnMpICU+JSBzZWxlY3QodmFsdWUpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fZG90cGxvdC5odG1sDQpkb3RwbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB2YWx1ZSkpICsNCiAgICAjIGdlb21fZGVuc2l0eSgpICsNCiAgICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMSkgKw0KICAgICMgZ2VvbV9kb3RwbG90KG1ldGhvZD0iaGlzdG9kb3QiLCBzdGFja2dyb3VwcyA9IFRSVUUsIHN0YWNrcmF0aW8gPSAxLjEsIGRvdHNpemUgPSAxLjIsIGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IE5VTEwpIA0KZG90cGxvdCA8LSBnZ3Bsb3RseShkb3RwbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KYm94cGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gMSwgeSA9IHZhbHVlKSkgKw0KICAgIGdlb21fYm94cGxvdCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgZ2d0aXRsZShwYXN0ZSgiZGlzdHJpYnV0aW9uIG9mIiwgbmFtZSwgc2VwPSIgIikpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkgDQpib3hwbG90IDwtIGdncGxvdGx5KGJveHBsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3FxLmh0bWwgDQpwbG90X3FxIDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHNhbXBsZSA9IHZhbHVlKSkgKw0KICAgIGdlb21fcXEoYWxwaGEgPSAwLjUpICsNCiAgICBnZW9tX3FxX2xpbmUoKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkNCnBsb3RfcXEgPC0gZ2dwbG90bHkocGxvdF9xcSkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdCh0aXRsZSA9IG5hbWUpKQ0KDQojIGh0dHBzOi8vcGxvdGx5LmNvbS9yL3N1YnBsb3RzLw0KZmlnIDwtIHN1YnBsb3QoZG90cGxvdCwgYm94cGxvdCwgcGxvdF9xcSwgbnJvd3MgPSAzLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjUsIDAuMiwgMC4zKSwgc2hhcmVYID0gVFJVRSkgDQoNCmZpZw0KYGBgDQoNCi0tLQ0KdW5pdmFyaWF0ZSBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZQ0KLS0tIA0KZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUgaXMgcG9pc3NvbiBkaXN0cmlidXRlZCwgbGlrZXMgdmVyeSBzaW1pbGFyIHRvIG5vX29mX2Fzc2V0cywgbWVkaWFuIGlzIDAuMiwgdXBwZXIgZmVuY2UgaXMgMS4xLCBtYXggaXMgNC43DQoNCmBgYHtyfQ0KIyBvbmUgdmFyaWFibGUsIGNvbnRpbnVvdXMgeCwgc2hvdyBkaXN0cmlidXRpb24NCm5hbWUgPSAnZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUnDQpkZiA8LSBwbGFzdGljICU+JSByZW5hbWUodmFsdWUgPSBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSkgJT4lIHNlbGVjdCh2YWx1ZSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9kb3RwbG90Lmh0bWwNCmRvdHBsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IHZhbHVlKSkgKw0KICAgICMgZ2VvbV9kZW5zaXR5KCkgKw0KICAgIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4xKSArDQogICAgIyBnZW9tX2RvdHBsb3QobWV0aG9kPSJoaXN0b2RvdCIsIHN0YWNrZ3JvdXBzID0gVFJVRSwgc3RhY2tyYXRpbyA9IDEuMSwgZG90c2l6ZSA9IDEuMiwgYmlud2lkdGggPSAxKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkgDQpkb3RwbG90IDwtIGdncGxvdGx5KGRvdHBsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQpib3hwbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSAxLCB5ID0gdmFsdWUpKSArDQogICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBnZ3RpdGxlKHBhc3RlKCJkaXN0cmlidXRpb24gb2YiLCBuYW1lLCBzZXA9IiAiKSkgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBOVUxMKSANCmJveHBsb3QgPC0gZ2dwbG90bHkoYm94cGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fcXEuaHRtbCANCnBsb3RfcXEgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoc2FtcGxlID0gdmFsdWUpKSArDQogICAgZ2VvbV9xcShhbHBoYSA9IDAuNSkgKw0KICAgIGdlb21fcXFfbGluZSgpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIHRoZW1lX21pbmltYWwoKQ0KcGxvdF9xcSA8LSBnZ3Bsb3RseShwbG90X3FxKSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSwgeGF4aXMgPSBsaXN0KHRpdGxlID0gbmFtZSkpDQoNCiMgaHR0cHM6Ly9wbG90bHkuY29tL3Ivc3VicGxvdHMvDQpmaWcgPC0gc3VicGxvdChkb3RwbG90LCBib3hwbG90LCBwbG90X3FxLCBucm93cyA9IDMsIG1hcmdpbiA9IDAsIGhlaWdodHMgPSBjKDAuNSwgMC4yLCAwLjMpLCBzaGFyZVggPSBUUlVFKSANCg0KZmlnDQpgYGANCg0KLS0tDQp1bml2YXJpYXRlIHJpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlDQotLS0NCnJpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlIGlzIHBvaXNzb24gZGlzdHJpYnV0ZWQsIGxpa2VzIHZlcnkgc2ltaWxhciB0byBub19vZl9hc3NldHMsIG1lZGlhbiBpcyAwLjIsIHVwcGVyIGZlbmNlIGlzIDEuMSwgbWF4IGlzIDQuNSwNCnZlcnkgc2ltaWxhciB0byBmbGV4aWJsZV9mb3JtYXRfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZSwgYnV0IHdpdGggbGVzcyBvdXRsaWVycw0KDQpgYGB7cn0NCiMgb25lIHZhcmlhYmxlLCBjb250aW51b3VzIHgsIHNob3cgZGlzdHJpYnV0aW9uDQpuYW1lID0gJ3JpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlJw0KZGYgPC0gcGxhc3RpYyAlPiUgcmVuYW1lKHZhbHVlID0gcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUpICU+JSBzZWxlY3QodmFsdWUpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fZG90cGxvdC5odG1sDQpkb3RwbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB2YWx1ZSkpICsNCiAgICAjIGdlb21fZGVuc2l0eSgpICsNCiAgICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMSkgKw0KICAgICMgZ2VvbV9kb3RwbG90KG1ldGhvZD0iaGlzdG9kb3QiLCBzdGFja2dyb3VwcyA9IFRSVUUsIHN0YWNrcmF0aW8gPSAxLjEsIGRvdHNpemUgPSAxLjIsIGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IE5VTEwpIA0KZG90cGxvdCA8LSBnZ3Bsb3RseShkb3RwbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KYm94cGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gMSwgeSA9IHZhbHVlKSkgKw0KICAgIGdlb21fYm94cGxvdCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgZ2d0aXRsZShwYXN0ZSgiZGlzdHJpYnV0aW9uIG9mIiwgbmFtZSwgc2VwPSIgIikpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkgDQpib3hwbG90IDwtIGdncGxvdGx5KGJveHBsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3FxLmh0bWwgDQpwbG90X3FxIDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHNhbXBsZSA9IHZhbHVlKSkgKw0KICAgIGdlb21fcXEoYWxwaGEgPSAwLjUpICsNCiAgICBnZW9tX3FxX2xpbmUoKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkNCnBsb3RfcXEgPC0gZ2dwbG90bHkocGxvdF9xcSkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdCh0aXRsZSA9IG5hbWUpKQ0KDQojIGh0dHBzOi8vcGxvdGx5LmNvbS9yL3N1YnBsb3RzLw0KZmlnIDwtIHN1YnBsb3QoZG90cGxvdCwgYm94cGxvdCwgcGxvdF9xcSwgbnJvd3MgPSAzLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjUsIDAuMiwgMC4zKSwgc2hhcmVYID0gVFJVRSkgDQoNCmZpZw0KYGBgDQoNCi0tLQ0KdW5pdmFyaWF0ZSB0b3RhbF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlDQotLS0NCnJpZ2lkX2Zvcm1hdF9jb250cmlidXRpb25fdG9fc3VwX3dhc3RlIGlzIHBvaXNzb24gZGlzdHJpYnV0ZWQsIGxpa2VzIHZlcnkgc2ltaWxhciB0byBub19vZl9hc3NldHMgKGFnYWluKSwgbWVkaWFuIGlzIDAuNDUsIHVwcGVyIGZlbmNlIGlzIDEuOSwgbWF4IGlzIDUuOQ0KaXMgc3VtIG9mIGZsZXhpYmxlX2Zvcm0gKyByaWdpZF9mb3JtDQoNCmBgYHtyfQ0KIyBvbmUgdmFyaWFibGUsIGNvbnRpbnVvdXMgeCwgc2hvdyBkaXN0cmlidXRpb24NCm5hbWUgPSAndG90YWxfY29udHJpYnV0aW9uX3RvX3N1cF93YXN0ZScNCmRmIDwtIHBsYXN0aWMgJT4lIHJlbmFtZSh2YWx1ZSA9IHRvdGFsX2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUpICU+JSBzZWxlY3QodmFsdWUpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fZG90cGxvdC5odG1sDQpkb3RwbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB2YWx1ZSkpICsNCiAgICAjIGdlb21fZGVuc2l0eSgpICsNCiAgICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMSkgKw0KICAgICMgZ2VvbV9kb3RwbG90KG1ldGhvZD0iaGlzdG9kb3QiLCBzdGFja2dyb3VwcyA9IFRSVUUsIHN0YWNrcmF0aW8gPSAxLjEsIGRvdHNpemUgPSAxLjIsIGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IE5VTEwpIA0KZG90cGxvdCA8LSBnZ3Bsb3RseShkb3RwbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KYm94cGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gMSwgeSA9IHZhbHVlKSkgKw0KICAgIGdlb21fYm94cGxvdCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgZ2d0aXRsZShwYXN0ZSgiZGlzdHJpYnV0aW9uIG9mIiwgbmFtZSwgc2VwPSIgIikpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkgDQpib3hwbG90IDwtIGdncGxvdGx5KGJveHBsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3FxLmh0bWwgDQpwbG90X3FxIDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHNhbXBsZSA9IHZhbHVlKSkgKw0KICAgIGdlb21fcXEoYWxwaGEgPSAwLjUpICsNCiAgICBnZW9tX3FxX2xpbmUoKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkNCnBsb3RfcXEgPC0gZ2dwbG90bHkocGxvdF9xcSkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSksIHhheGlzID0gbGlzdCh0aXRsZSA9IG5hbWUpKQ0KDQojIGh0dHBzOi8vcGxvdGx5LmNvbS9yL3N1YnBsb3RzLw0KZmlnIDwtIHN1YnBsb3QoZG90cGxvdCwgYm94cGxvdCwgcGxvdF9xcSwgbnJvd3MgPSAzLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjUsIDAuMiwgMC4zKSwgc2hhcmVYID0gVFJVRSkgDQoNCmZpZw0KYGBgDQoNCi0tLQ0KdW5pdmFyaWF0ZSB0b3RhbF93YXN0ZV9kaXZfcHJvZHVjdGlvbg0KLS0tDQpyYXRpb24gb2Ygc3VwX3dhc3RlIHRvIHByb2R1Y2VkIHBvbHltZXJzIGlzIGJldHdlZW4gbWluIDAuMyBhbmQgbWF4IDEuMCBhbmQgaGFzIG1lZGlhbiAwLjUsIG1vc3QgZGF0YSBsaWVzIGJldHdlZW4gMC40IGFuZCAwLjYsIGJ1dCB0aGVyZSBpcyBhIGhpZ2ggc3Bpa2UgYXQgMS4wICh3aXRoIGNvdW50IDE1KQ0KDQpgYGB7cn0NCiMgb25lIHZhcmlhYmxlLCBjb250aW51b3VzIHgsIHNob3cgZGlzdHJpYnV0aW9uDQpuYW1lID0gJ3RvdGFsX3dhc3RlX2Rpdl9wcm9kdWN0aW9uJw0KZGYgPC0gcGxhc3RpYyAlPiUgcmVuYW1lKHZhbHVlID0gdG90YWxfd2FzdGVfZGl2X3Byb2R1Y3Rpb24pICU+JSBzZWxlY3QodmFsdWUpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fZG90cGxvdC5odG1sDQpkb3RwbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB2YWx1ZSkpICsNCiAgICAjIGdlb21fZGVuc2l0eSgpICsNCiAgICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDAuMDEpICsNCiAgICAjIGdlb21fZG90cGxvdChtZXRob2Q9Imhpc3RvZG90Iiwgc3RhY2tncm91cHMgPSBUUlVFLCBzdGFja3JhdGlvID0gMS4xLCBkb3RzaXplID0gMS4yLCBiaW53aWR0aCA9IDEpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBOVUxMKSANCmRvdHBsb3QgPC0gZ2dwbG90bHkoZG90cGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCmJveHBsb3QgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoeCA9IDEsIHkgPSB2YWx1ZSkpICsNCiAgICBnZW9tX2JveHBsb3QoKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIGdndGl0bGUocGFzdGUoImRpc3RyaWJ1dGlvbiBvZiIsIG5hbWUsIHNlcD0iICIpKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IE5VTEwpIA0KYm94cGxvdCA8LSBnZ3Bsb3RseShib3hwbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9xcS5odG1sIA0KcGxvdF9xcSA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyhzYW1wbGUgPSB2YWx1ZSkpICsNCiAgICBnZW9tX3FxKGFscGhhID0gMC41KSArDQogICAgZ2VvbV9xcV9saW5lKCkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgdGhlbWVfbWluaW1hbCgpDQpwbG90X3FxIDwtIGdncGxvdGx5KHBsb3RfcXEpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpLCB4YXhpcyA9IGxpc3QodGl0bGUgPSBuYW1lKSkNCg0KIyBodHRwczovL3Bsb3RseS5jb20vci9zdWJwbG90cy8NCmZpZyA8LSBzdWJwbG90KGRvdHBsb3QsIGJveHBsb3QsIHBsb3RfcXEsIG5yb3dzID0gMywgbWFyZ2luID0gMCwgaGVpZ2h0cyA9IGMoMC41LCAwLjIsIDAuMyksIHNoYXJlWCA9IFRSVUUpIA0KDQpmaWcNCmBgYA0KDQotLS0NCmNvbXBhcmUgcmlnaWRfZm9ybWF0IGFuZCBmbGV4aWJsZV9mb3JtYXQgDQotLS0NCmNvbXBhcmluZyByaWdpZF9mb3JtYXQgYW5kIGZsZXhpYmxlX2Zvcm1hdCBzaG93cyB0aGF0IHVwIHRvIHRoZSB1cHBlciBmZW5jZSAxLjEsIHRoZSBkaXN0cmlidXRpb24gaXMgc2ltaWxhciwgYnV0IHRoZXJlIGFyZSBtb3JlIGJpZ2dlciAoPjMpIG91dGxpZXJzIGluIGZsZXhpYmxlDQoNCmBgYHtyfQ0KIyB0d28gdmFyaWFibGVzLCBib3RoIGNvbnRpbnVvdXMgeCwgY29tcGFyZSBkaXN0cmlidXRpb25zDQpuYW1lID0gYygnZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUnLCAncmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUnKQ0KZGYgPC0gcGxhc3RpYyAlPiUgcmVuYW1lKGZsZXhpYmxlID0gZmxleGlibGVfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUsIHJpZ2lkID0gcmlnaWRfZm9ybWF0X2NvbnRyaWJ1dGlvbl90b19zdXBfd2FzdGUpICU+JSBzZWxlY3QoZmxleGlibGUsIHJpZ2lkKSAlPiUgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKGZsZXhpYmxlLHJpZ2lkKSkNCg0KYm94cGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gbmFtZSwgeSA9IHZhbHVlLCBjb2xvdXIgPSBuYW1lKSkgKw0KICAgIGdlb21fYm94cGxvdCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgZ2d0aXRsZShwYXN0ZSgiY29tcGFyZSAiLCBuYW1lWzFdLCAiYW5kIiwgbmFtZVsyXSwgc2VwPSIgIikpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkgDQpib3hwbG90IDwtIGdncGxvdGx5KGJveHBsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX2RvdHBsb3QuaHRtbA0KZG90cGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gdmFsdWUsIGZpbGwgPSBuYW1lKSkgKw0KICAgICMgZ2VvbV9kZW5zaXR5KCkgKw0KICAgIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4xLCBhbHBoYSA9IDAuNSwgcG9zaXRpb24gPSAiaWRlbnRpdHkiKSArDQogICAgIyBnZW9tX2RvdHBsb3QobWV0aG9kPSJoaXN0b2RvdCIsIHN0YWNrZ3JvdXBzID0gVFJVRSwgc3RhY2tyYXRpbyA9IDEsIGRvdHNpemUgPSAwLjIzLCBiaW53aWR0aCA9IDAuMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IE5VTEwpIA0KZG90cGxvdCA8LSBnZ3Bsb3RseShkb3RwbG90KSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdChzaG93dGlja2xhYmVscyA9IEZBTFNFLCBzaG93Z3JpZCA9IEZBTFNFKSkNCg0KIyBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvZ2VvbV9xcS5odG1sIA0KcGxvdF9xcSA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyhzYW1wbGUgPSB2YWx1ZSwgY29sb3VyID0gbmFtZSkpICsNCiAgICBnZW9tX3FxKGFscGhhID0gMC41KSArDQogICAgZ2VvbV9xcV9saW5lKGFscGhhID0gMC41KSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgDQpwbG90X3FxIDwtIGdncGxvdGx5KHBsb3RfcXEpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vcGxvdGx5LmNvbS9yL3N1YnBsb3RzLw0KZmlnIDwtIHN1YnBsb3QoZG90cGxvdCwgYm94cGxvdCwgcGxvdF9xcSwgbnJvd3MgPSAzLCBtYXJnaW4gPSAwLCBoZWlnaHRzID0gYygwLjUsIDAuMiwgMC4zKSwgc2hhcmVYID0gVFJVRSkgJT4lIGxheW91dCh4YXhpcyA9IGxpc3QodGl0bGUgPSBwYXN0ZShuYW1lWzFdLCAiPGJyPiIsIG5hbWVbMl0sIHNlcD0iIikpKQ0KDQpmaWcNCmBgYA0KDQoNCg0KLS0tDQphcHBlbmRpeDogb2xkIGV4cGVyaW1lbnRhbCBwbG90cw0KLS0tDQpgYGB7cn0NCmFzc2V0c19wbG90X2hpc3QgPC0gcGxhc3RpYyAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gbm9fb2ZfYXNzZXRzKSkgKw0KICAgIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9uIG9mIG5vX29mX2Fzc2V0cyIpDQoNCmdncGxvdGx5KGFzc2V0c19wbG90X2hpc3QpDQpgYGANCmBgYHtyfQ0KYXNzZXRzX3Bsb3RfYm94IDwtIHBsYXN0aWMgJT4lDQogIGdncGxvdChhZXMoeCA9IDEsIHkgPSBub19vZl9hc3NldHMpKSArDQogICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgIGdlb21faml0dGVyKGFscGhhID0gMC41LCB3aWR0aCA9IDAuMTUpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgZ2d0aXRsZSgiRGlzdHJpYnV0aW9uIG9mIG5vX29mX2Fzc2V0cyIpDQoNCmdncGxvdGx5KGFzc2V0c19wbG90X2JveCkNCmBgYA0KYGBge3J9DQphc3NldHNfcGxvdF9ib3ggPC0gcGxhc3RpYyAlPiUNCiAgbXV0YXRlKCB4ID0gMSApICU+JQ0KICBnZ3Bsb3QoYWVzKHkgPSBub19vZl9hc3NldHMsIHg9MSkpICsNCiAgICBnZW9tX2JveHBsb3QoKSArDQogICAgZ2VvbV9kb3RwbG90KGJpbmF4aXM9J3knLCBzdGFja2Rpcj0nY2VudGVyJywgYmlud2lkdGggPSAxKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIGdndGl0bGUoIkRpc3RyaWJ1dGlvbiBvZiBub19vZl9hc3NldHMiKQ0KDQphc3NldHNfcGxvdF9ib3gNCmBgYA0KYGBge3J9DQphc3NldHNfcGxvdF9kZW5zaXR5IDwtIHBsYXN0aWMgJT4lDQogIGdncGxvdChhZXMoeCA9IG5vX29mX2Fzc2V0cykpICsNCiAgICBnZW9tX2hpc3RvZ3JhbShhZXMoeT0uLmRlbnNpdHkuLikpICsNCiAgICBnZW9tX2RlbnNpdHkoKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKCJEaXN0cmlidXRpb24gb2Ygbm9fb2ZfYXNzZXRzIikNCg0KZ2dwbG90bHkoYXNzZXRzX3Bsb3RfZGVuc2l0eSkNCmBgYA0KYGBge3J9DQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX2RvdHBsb3QuaHRtbA0KYXNzZXRzX3Bsb3RfZG90IDwtIHBsYXN0aWMgJT4lDQogIGdncGxvdChhZXMoeCA9IG5vX29mX2Fzc2V0cykpICsNCiAgICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDEpICsNCiAgICBnZW9tX2RvdHBsb3QobWV0aG9kPSJoaXN0b2RvdCIsIHN0YWNrZ3JvdXBzID0gVFJVRSwgc3RhY2tyYXRpbyA9IDEuMSwgZG90c2l6ZSA9IDEsIGJpbndpZHRoID0gMSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IE5VTEwpICsNCiAgICBnZ3RpdGxlKCJEaXN0cmlidXRpb24gb2Ygbm9fb2ZfYXNzZXRzIikNCg0KYXNzZXRzX3Bsb3RfZG90DQpgYGANCmBgYHtyfQ0KbmFtZSA9ICdub19vZl9hc3NldHMnDQpkZiA8LSBwbGFzdGljICU+JSByZW5hbWUoeSA9IG5vX29mX2Fzc2V0cykgJT4lIHNlbGVjdCh5KQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3FxLmh0bWwgDQpwbG90X3FxIDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHNhbXBsZSA9IHkpKSArDQogICAgZ2VvbV9xcSgpICsNCiAgICBnZW9tX3FxX2xpbmUoKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKHBhc3RlKCJxcSBwbG90IGZvciIsIG5hbWUsIHNlcD0iICIpKQ0KcGxvdF9xcSA8LSBnZ3Bsb3RseShwbG90X3FxKQ0KDQojIFVzZSBmaXRkaXN0ciBmcm9tIE1BU1MgdG8gZXN0aW1hdGUgZGlzdHJpYnV0aW9uIHBhcmFtcw0KIyBodHRwczovL3JkcnIuaW8vY3Jhbi9NQVNTL21hbi9maXRkaXN0ci5odG1sDQpwYXJhbXMgPC0gYXMubGlzdChNQVNTOjpmaXRkaXN0cihkZiR5LCAidCIpJGVzdGltYXRlKQ0KcGxvdF9xcV9maXQgPC0gZGYgJT4lDQogIGdncGxvdChhZXMoc2FtcGxlID0geSkpICsNCiAgICBnZW9tX3FxKGRpc3RyaWJ1dGlvbiA9IHF0LCBkcGFyYW1zID0gcGFyYW1zWyJkZiJdKSArDQogICAgZ2VvbV9xcV9saW5lKGRpc3RyaWJ1dGlvbiA9IHF0LCBkcGFyYW1zID0gcGFyYW1zWyJkZiJdKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKHBhc3RlKCJxcSBwbG90IGZvciIsIG5hbWUsICJ3aXRob3V0IGxlZnQgYW5kIHdpdGggZml0ZGlzdHIgcmlnaHQiLCBzZXA9IiAiKSkNCnBsb3RfcXFfZml0IDwtIGdncGxvdGx5KHBsb3RfcXFfZml0KQ0KDQojIGh0dHBzOi8vcGxvdGx5LmNvbS9yL3N1YnBsb3RzLw0Kc3VicGxvdChwbG90X3FxLCBwbG90X3FxX2ZpdCkNCmBgYA0KYGBge3J9DQpuYW1lID0gJ3Byb2R1Y3Rpb25fb2ZfaW5fc2NvcGVfcG9seW1lcnMnDQpkZiA8LSBwbGFzdGljICU+JSByZW5hbWUoeSA9IHByb2R1Y3Rpb25fb2ZfaW5fc2NvcGVfcG9seW1lcnMpICU+JSBzZWxlY3QoeSkNCg0KYm94cGxvdCA8LSBkZiAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gMSwgeSA9IHkpKSArDQogICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBnZ3RpdGxlKHBhc3RlKCJkaXN0cmlidXRpb24gb2YiLCBuYW1lLCBzZXA9IiAiKSkgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBOVUxMKSANCmJveHBsb3QgPC0gZ2dwbG90bHkoYm94cGxvdCkgJT4lIGxheW91dCh5YXhpcyA9IGxpc3Qoc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSwgc2hvd2dyaWQgPSBGQUxTRSkpDQoNCiMgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dlb21fZG90cGxvdC5odG1sDQpkb3RwbG90IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB5KSkgKw0KICAgICMgZ2VvbV9kZW5zaXR5KCkgKw0KICAgICMgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgZ2VvbV9kb3RwbG90KG1ldGhvZD0iaGlzdG9kb3QiLCBzdGFja2dyb3VwcyA9IFRSVUUsIHN0YWNrcmF0aW8gPSAxLjEsIGRvdHNpemUgPSAxLjIsIGJpbndpZHRoID0gMC4xKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCkgDQpkb3RwbG90IDwtIGdncGxvdGx5KGRvdHBsb3QpICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHNob3d0aWNrbGFiZWxzID0gRkFMU0UsIHNob3dncmlkID0gRkFMU0UpKQ0KDQojIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZW9tX3FxLmh0bWwgDQpwbG90X3FxIDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHNhbXBsZSA9IHkpKSArDQogICAgZ2VvbV9xcSgpICsNCiAgICBnZW9tX3FxX2xpbmUoKSArDQogICAgdGhlbWVfbWluaW1hbCgpIA0KDQojIFVzZSBmaXRkaXN0ciBmcm9tIE1BU1MgdG8gZXN0aW1hdGUgZGlzdHJpYnV0aW9uIHBhcmFtcw0KcGFyYW1zIDwtIGFzLmxpc3QoTUFTUzo6Zml0ZGlzdHIoZGYkeSwgInQiKSRlc3RpbWF0ZSkNCnBsb3RfcXFfZml0IDwtIGRmICU+JQ0KICBnZ3Bsb3QoYWVzKHNhbXBsZSA9IHkpKSArDQogICAgZ2VvbV9xcShkaXN0cmlidXRpb24gPSBxdCwgZHBhcmFtcyA9IHBhcmFtc1siZGYiXSkgKw0KICAgIGdlb21fcXFfbGluZShkaXN0cmlidXRpb24gPSBxdCwgZHBhcmFtcyA9IHBhcmFtc1siZGYiXSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSANCg0KIyBodHRwczovL3Bsb3RseS5jb20vci9zdWJwbG90cy8NCnMxIDwtIHN1YnBsb3QoZG90cGxvdCwgYm94cGxvdCwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLjAzLCBoZWlnaHRzID0gYygwLjc1LCAwLjI1KSkNCnMyIDwtIHN1YnBsb3QocGxvdF9xcSwgcGxvdF9xcV9maXQpDQpmaWcgPC0gc3VicGxvdChzMSwgczIsIG5yb3dzID0gMiwgbWFyZ2luID0gMC4wMywgaGVpZ2h0cyA9IGMoMC42LCAwLjQpKSANCg0KZmlnDQpgYGANCg0KDQoNCg==